import 'dart:math';

import 'package:flutter/material.dart';

class BaseCircleProgress extends StatefulWidget {
  /// 画笔大小
  final double strokeWidth;

  ///显示进度
  final double showProgress;

  ///显示标题
  final String title;

  ///显示副标题
  final String subTitle;

  /// 圆弧颜色
  final Color color;

  /// 圆弧的底色
  final Color arcBgColor;

  ///绘制标题文字大小
  final double titleFontSize;

  ///绘制副标题文字大小
  final double subTitleFontSize;

  ///标题颜色
  final Color titleColor;

  ///副标题颜色
  final Color subTitleColor;

  ///主副标题间距
  final double spacing;

  const BaseCircleProgress({
    Key key,
    @required this.showProgress,
    @required this.title,
    this.strokeWidth = 5,
    this.subTitle = '',
    this.color = Colors.lightBlueAccent,
    this.arcBgColor,
    this.titleFontSize = 12,
    this.subTitleFontSize = 12,
    this.titleColor = Colors.black,
    this.spacing = 8,
    this.subTitleColor = const Color(0xFF868686),
  }) : super(key: key);

  @override
  _BaseCircleProgressState createState() => _BaseCircleProgressState();
}

class _BaseCircleProgressState extends State<BaseCircleProgress> with SingleTickerProviderStateMixin {
  AnimationController _controller;

  @override
  void initState() {
    super.initState();
    _controller = AnimationController(
      duration: const Duration(milliseconds: 1500),
      vsync: this,
    )..forward();
  }

  @override
  void dispose() {
    _controller.dispose();
    super.dispose();
  }

  @override
  Widget build(BuildContext context) {
    return LayoutBuilder(builder: (context, constraints) {
      return Container(
        height: constraints.biggest.width,
        width: constraints.biggest.width,
        child: CustomPaint(
          painter: CircleProgressPainter(
            repaint: _controller,
            title: widget.title,
            showProgress: widget.showProgress,
            color: widget.color,
            arcBgColor: widget.arcBgColor,
            strokeWidth: widget.strokeWidth,
            subTitle: widget.subTitle,
            titleFontSize: widget.titleFontSize,
            subTitleFontSize: widget.subTitleFontSize,
            titleColor: widget.titleColor,
            subTitleColor: widget.subTitleColor,
            spacing: widget.spacing,
          ),
        ),
      );
    });
  }
}

class CircleProgressPainter extends CustomPainter {
  ///动画数值
  final Animation<double> repaint;

  /// 当前值
  final double showProgress;

  /// 画笔大小
  final double strokeWidth;

  /// 圆弧颜色
  final Color color;

  /// 圆弧的底色
  final Color arcBgColor;

  /// 显示标题
  final String title;

  ///显示副标题
  final String subTitle;

  ///绘制文字大小
  final double titleFontSize;
  final double subTitleFontSize;

  ///标题颜色
  final Color titleColor;

  ///副标题颜色
  final Color subTitleColor;

  ///主副标题间距
  final double spacing;

  CircleProgressPainter({
    @required this.repaint,
    @required this.title,
    @required this.showProgress,
    this.color,
    this.arcBgColor,
    this.strokeWidth = 5,
    this.titleFontSize = 8,
    this.subTitleFontSize = 8,
    this.subTitle = '',
    this.titleColor = Colors.black,
    this.spacing = 8,
    this.subTitleColor = const Color(0xFF868686),
  }) : super(repaint: repaint);

  final TextPainter _textPainter = TextPainter(textDirection: TextDirection.ltr);
  final TextPainter _textSubPainter = TextPainter(textDirection: TextDirection.ltr);

  /// 自定义画笔
  Paint _paint = Paint();
  double radius = 0.0;

  @override
  void paint(Canvas canvas, Size size) {
    _paint = Paint()
      ..style = PaintingStyle.stroke // 是否0填充
      ..strokeWidth = this.strokeWidth // 画笔大小
      ..color = this.color ?? Colors.blue // 画笔颜色
      ..isAntiAlias = true // 是否抗锯齿
      ..filterQuality = FilterQuality.high; // 颜色渲染模式质量

    /// 计算半径
    radius = (min(size.width, size.height) / 2);

    /// 绘制背景圆
    _paint..color = Color(0xFFEFEFEF);

    /// 移动绘画中心
    canvas.translate(size.width / 2, size.height / 2);
    canvas.drawCircle(Offset(0, 0), radius - this.strokeWidth, _paint);

    /// 绘制底层圆弧
    if (this.arcBgColor != null) _drawBgArc(canvas, size);

    /// 绘制圆弧
    _drawArc(canvas, size);

    ///绘制文本情况
    _drawText(canvas, title: title, subTitle: subTitle, offset: Offset(0, 0));
  }

  void _drawArc(Canvas canvas, Size size) {
    canvas.save();
    canvas.rotate(-pi / 2);
    _paint..color = this.color ?? Colors.blue;

    Rect rect = Rect.fromCircle(center: Offset(0, 0), radius: radius - this.strokeWidth);

    /// 开始的角度位置
    double startAngle = 0;

    /// 结束角位置
    double sweepAngle = 2 * pi * showProgress;

    /// 绘制
    canvas.drawArc(rect, startAngle, sweepAngle * repaint.value, false, _paint);
    canvas.restore();
  }

  /// 绘制底层圆弧
  void _drawBgArc(Canvas canvas, Size size) {
    canvas.save();
    canvas.rotate(-pi / 2);
    _paint..color = this.arcBgColor;

    Rect rect = Rect.fromCircle(center: Offset(0, 0), radius: radius - this.strokeWidth);

    /// 开始的角度位置
    double startAngle = 0;

    /// 结束角位置
    double sweepAngle = 2 * pi;

    /// 绘制
    canvas.drawArc(rect, startAngle, sweepAngle * repaint.value, false, _paint);
    canvas.restore();
  }

  ///标题和副标题一起绘制
  void _drawText(Canvas canvas, {String title, String subTitle, Offset offset = Offset.zero}) {
    ///绘制标题
    TextSpan text = TextSpan(text: title, style: TextStyle(fontSize: titleFontSize, color: titleColor));
    _textPainter.text = text;
    _textPainter.layout(); // 进行布局
    Size textSize = _textPainter.size;

    ///绘制副标题
    TextSpan subText = TextSpan(text: subTitle, style: TextStyle(fontSize: subTitleFontSize, color: subTitleColor));
    _textSubPainter.text = subText;
    _textSubPainter.layout(); // 进行布局
    Size subTextSize = _textSubPainter.size;

    Offset textOffsetPos;
    if (subTitle == null || subTitle.isEmpty) {
      textOffsetPos = Offset(offset.dx - textSize.width / 2, offset.dy - textSize.height / 2);
    } else {
      textOffsetPos = Offset(offset.dx - textSize.width / 2, offset.dy - textSize.height - spacing / 2);
    }
    _textPainter.paint(canvas, textOffsetPos);

    Offset subTextOffsetPos = Offset(offset.dx - subTextSize.width / 2, offset.dy + spacing / 2);
    _textSubPainter.paint(canvas, subTextOffsetPos);
  }

  /// 这个方法控制的是是否需要重绘
  @override
  bool shouldRepaint(CustomPainter oldDelegate) {
    return true;
  }
}
